package server

import (
	"archive/zip"
	"io"
	"lan-file-transfer/core"
	"lan-file-transfer/models"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true // 允许所有来源
	},
}

// handleAuth 处理认证请求
func (s *Server) handleAuth(c *gin.Context) {
	var req models.AuthRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, models.ErrorResponse("请求参数错误"))
		return
	}

	clientIP := c.ClientIP()

	// 检查IP是否被锁定
	locked, remaining := s.securityMgr.CheckIPLocked(clientIP)
	if locked {
		c.JSON(http.StatusTooManyRequests, models.ErrorResponse(
			"密码错误次数过多,请在"+remaining.String()+"后重试",
		))
		return
	}

	// 验证密码
	if !s.securityMgr.VerifyPassword(req.Password) {
		s.securityMgr.RecordFailedAttempt(clientIP)
		c.JSON(http.StatusUnauthorized, models.ErrorResponse("密码错误"))
		return
	}

	// 清除失败记录
	s.securityMgr.ClearFailedAttempt(clientIP)

	// 生成Token
	token, err := core.GenerateToken(clientIP)
	if err != nil {
		c.JSON(http.StatusInternalServerError, models.ErrorResponse("生成令牌失败"))
		return
	}

	c.JSON(http.StatusOK, models.SuccessResponse(models.AuthResponse{
		Token: token,
	}))
}

// handleGetFiles 获取文件列表
func (s *Server) handleGetFiles(c *gin.Context) {
	files := s.fileManager.GetAllFiles()
	c.JSON(http.StatusOK, models.SuccessResponse(files))
}

// handleGetFilterRules 获取文件过滤规则
func (s *Server) handleGetFilterRules(c *gin.Context) {
	filter := s.fileManager.GetFilter()
	c.JSON(http.StatusOK, models.SuccessResponse(filter))
}

// handleDownload 处理文件下载
func (s *Server) handleDownload(c *gin.Context) {
	fileID := c.Param("id")

	// 移除并发限制，允许无限制下载
	// if !s.semaphore.TryAcquire() {
	// 	c.JSON(http.StatusTooManyRequests, models.ErrorResponse("下载队列已满,请稍后重试"))
	// 	return
	// }
	// defer s.semaphore.Release()

	// 获取文件信息
	fileInfo, err := s.fileManager.GetFile(fileID)
	if err != nil {
		c.JSON(http.StatusNotFound, models.ErrorResponse("文件不存在"))
		return
	}

	// 检查文件是否存在
	if _, err := os.Stat(fileInfo.Path); os.IsNotExist(err) {
		c.JSON(http.StatusNotFound, models.ErrorResponse("文件不存在"))
		return
	}

	// 如果是目录，打包成ZIP
	if fileInfo.Type == "directory" {
		s.downloadDirectory(c, fileInfo)
		return
	}

	// 单文件直接发送
	c.Header("Content-Disposition", "attachment; filename="+fileInfo.Name)
	c.Header("Content-Type", "application/octet-stream")
	c.File(fileInfo.Path)
}

// downloadDirectory 下载文件夹（压缩成ZIP）
func (s *Server) downloadDirectory(c *gin.Context, fileInfo *models.FileInfo) {
	// 设置响应头
	zipName := fileInfo.Name + ".zip"
	c.Header("Content-Disposition", "attachment; filename="+zipName)
	c.Header("Content-Type", "application/zip")

	// 创建ZIP writer，直接写入响应
	zipWriter := zip.NewWriter(c.Writer)
	defer zipWriter.Close()

	// 获取文件过滤器
	filter := s.fileManager.GetFilter()

	// 递归添加文件到ZIP
	err := filepath.Walk(fileInfo.Path, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil // 跳过错误
		}

		// 跳过根目录本身
		if path == fileInfo.Path {
			return nil
		}

		// 使用过滤器检查是否应该排除
		if filter.ShouldExclude(path, info.IsDir()) {
			if info.IsDir() {
				return filepath.SkipDir // 跳过整个目录
			}
			return nil // 跳过文件
		}

		// 获取相对路径
		relPath, err := filepath.Rel(fileInfo.Path, path)
		if err != nil {
			return err
		}

		// 创建ZIP文件头
		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		// 设置文件名为相对路径
		header.Name = relPath

		// 如果是目录，名称以/结尾
		if info.IsDir() {
			header.Name += "/"
		} else {
			// 设置压缩方法
			header.Method = zip.Deflate
		}

		// 创建文件
		writer, err := zipWriter.CreateHeader(header)
		if err != nil {
			return err
		}

		// 如果不是目录，写入文件内容
		if !info.IsDir() {
			file, err := os.Open(path)
			if err != nil {
				return err
			}
			defer file.Close()

			_, err = io.Copy(writer, file)
			if err != nil {
				return err
			}
		}

		return nil
	})

	if err != nil {
		// 如果出错，无法返回JSON（因为已经开始写响应了）
		// 只能在日志中记录
		return
	}
}

// handleBatchDownload 处理批量下载
func (s *Server) handleBatchDownload(c *gin.Context) {
	var req models.BatchDownloadRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, models.ErrorResponse("请求参数错误"))
		return
	}

	// 批量下载需要打包成ZIP,这里先返回错误,后续实现
	c.JSON(http.StatusNotImplemented, models.ErrorResponse("批量下载功能开发中"))
}

// handleWebSocket 处理WebSocket连接
func (s *Server) handleWebSocket(c *gin.Context) {
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		return
	}
	defer conn.Close()

	// 创建进度通道
	progressChan := make(chan models.DownloadProgress, 10)
	connID := core.GenerateUUID()
	s.progressChans.Store(connID, progressChan)
	defer s.progressChans.Delete(connID)

	// 心跳检测
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case progress := <-progressChan:
			// 发送进度信息
			if err := conn.WriteJSON(progress); err != nil {
				return
			}
		case <-ticker.C:
			// 发送心跳
			if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {
				return
			}
		}
	}
}
